<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>刷分2.0</title>
  <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <link rel="stylesheet" type="text/css" href="https://www.layuicdn.com/layui/css/layui.css" />
  <script src="https://www.layuicdn.com/layui/layui.js"></script>

  <style>
    .mods {
      padding: 30px;
      box-sizing: border-box;
    }
  </style>
</head>

<body>
  <div class="layui-tab layui-tab-brief mods" id="app">
    <ul class="layui-tab-title">
      <li @click="changeTable('0')" :class="[{'layui-this':currTab == 0}]">基础配置</li>
      <li @click="changeTable('1')" :class="[{'layui-this':currTab == 1}]">刷分记录</li>
    </ul>
    <div class="layui-tab-content" style="height: 100px">
      <div :class="['layui-tab-item',{'layui-show':currTab == 0}]">
        <form class="layui-form" action="">
          <div class="layui-form-item">
            <label class="layui-form-label">Token</label>
            <div class="layui-input-block">
              <input type="text" name="token" required lay-verify="required" placeholder="请输入平台Token" autocomplete="off"
                class="layui-input" v-model="baseConfig.token" />
            </div>
          </div>

          <div class="layui-form-item">
            <div class="layui-inline">
              <label class="layui-form-label">阅读间隔</label>
              <div class="layui-input-inline" style="width: 100px">
                <input type="number" lay-verify="required" name="time_min" autocomplete="off" class="layui-input"
                  v-model="baseConfig.time_min" />
              </div>
              <div class="layui-form-mid ayui-word-aux">-</div>
              <div class="layui-input-inline" style="width: 100px">
                <input type="number" lay-verify="required" name="time_max" autocomplete="off" class="layui-input"
                  v-model="baseConfig.time_max" />
              </div>
              <div class="layui-form-mid layui-word-aux">秒 （间隔是以15秒为基础，叠加随机间隔时间）</div>
            </div>
          </div>

          <div class="layui-form-item">
            <label class="layui-form-label">分数</label>
            <div class="layui-input-block">
              <input type="radio" name="fraction" value="max" title="刷满" :checked="baseConfig.fraction == 'max'" />
              <input type="radio" name="fraction" value="random" title="随机"
                :checked="baseConfig.fraction == 'random'" />
            </div>
          </div>

          <div class="layui-form-item">
            <label class="layui-form-label">随机最低</label>
            <div class="layui-input-block">
              <input type="text" name="fraction_min" placeholder="随机模式最低刷分数" autocomplete="off" class="layui-input"
                v-model="baseConfig.fraction_min" />
            </div>
          </div>

          <div class="layui-form-item">
            <div class="layui-input-block">
              <button class="layui-btn" lay-submit lay-filter="formDemo">开始</button>
              <div class="layui-btn layui-btn-primary" @click="stop">暂停</div>
            </div>
          </div>
        </form>

        <p v-for="item in tokenList" style="margin-top: 20px;">
          <a href="javascript:;" @click="baseConfig.token = item.value">
            {{item.name}}：{{item.value}}
          </a>
        </p>

      </div>
      <div :class="['layui-tab-item',{'layui-show':currTab == 1}]">
        <blockquote class="layui-elem-quote">
          <p>平台总分：{{score.sum}}</p>
          <p>今日总分：{{score.today}}/{{score.target}}</p>
          <p>最后一次请求：{{timer.lastTime}}</p>
          <p>间隔下次请求：{{timer.nextTime}} 秒后</p>
          <p>状态：{{statusMap[status]}}</p>
          <p style="color: red" v-if="status_msg && status <= 0">{{status_msg}}</p>
        </blockquote>
        <div class="layui-progress layui-progress-big" lay-filter="progress" lay-showPercent="yes">
          <div class="layui-progress-bar layui-bg-green" lay-percent="0%"></div>
        </div>

        <ul class="layui-timeline" style="margin-top: 20px">
          <li class="layui-timeline-item" v-for="item in log" :key="item.key">
            <i class="layui-icon layui-timeline-axis">&#xe63f;</i>
            <div class="layui-timeline-content layui-text">
              <h3 class="layui-timeline-title">文章ID：{{item.articelId}}</h3>
              <div>
                <div>请求时间：{{item.currTime}}</div>
                <div>预计阅读时长：{{item.waitTime}}</div>
                <div>当前分数：{{item.fraction}}</div>
                <div v-if="item.nextId">下一篇：{{item.nextId}}</div>
              </div>
            </div>
          </li>
        </ul>
      </div>
    </div>
  </div>
</body>

<script>
  var utils = (function () {
    function Tools() {
      var token = ''
      this.setToken = function (configToken = '') {
        token = configToken
      }

      this.request = function (url, data = '') {
        return new Promise((resolve, reject) => {
          if (!token || !url) {
            alert('填写配置后开始')
            app.changeTable('0')
            reject({
              stat: 0,
              message: '填写配置后开始'
            })
            return false
          }
          $.ajax({
            async: true,
            crossDomain: true,
            url: url,
            method: 'POST',
            headers: {
              authorization: token,
              'content-type': 'application/json',
              'cache-control': 'no-cache'
            },
            processData: false,
            data: data
          })
            .done(function (res) {
              if (res.code !== 0) {
                reject({
                  stat: res.code,
                  message: res.data || res
                })
              } else {
                resolve({
                  stat: 1,
                  data: res.data,
                  message: 'success'
                })
              }
            })
            .fail(function (res) {
              reject({
                stat: -1,
                message: res.responseText || res
              })
            })
        })
      }
    }

    var tools = new Tools()

    return {
      // 文章分类ID
      typeList: ['1736456913', '1736427556', '1736451638', '1765023144'],
      setToken: tools.setToken,
      request: tools.request,
      progress: null
    }
  })()

  layui.use(['form', 'element'], function () {
    var form = layui.form,
      element = layui.element //Tab的切换功能，切换事件监听等，需要依赖element模块

    utils.progress = element.progress

    //监听提交
    form.on('submit(formDemo)', function (data) {
      window.localStorage.setItem('config', JSON.stringify(data.field))
      utils.setToken(data.field.token)
      // v-model 绑定不了layui的radio
      app.config = data.field
      app.start()
      return false
    })
  })

  var app = new Vue({
    el: '#app',
    data: {
      currTab: 0,
      config: {}, // form 表单数据
      baseConfig: {}, // form 表单数据
      status: 0, // 当前状态 -1:不能开始; 0:暂停; 1:进行中
      statusMap: {
        '-1': '请求错误',
        0: '暂停/未开始',
        1: '进行中',
        2: '阅读中'
      },
      status_msg: '', // 当前状态描述
      score: {
        sum: 0, // 平台总分
        today: 0, // 今天得分
        target: 150 // 目标总分
      },
      timer: {
        timeOut: null,
        interval: null,
        lastTime: '',
        nextTime: ''
      },
      articelIds: [], // 文章列表
      idsMapLabelid: {},
      readingId: '', // 当前阅读中的ID
      log: [], // 日志
      tokenList: [
        {
          name: 'Jioho',
          value: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJvcGVuaWQiOiJvX1UtcTVTeGJpaDBzOWdHU1F3YmcwRUc4SUFnIiwiaWF0IjoxNjAyMjI1MDYyLCJleHAiOjE2MDQ4MTcwNjJ9.FRG5sbPm7DDfo5kcrZPRK41b_ii-XriogJ5t2zClPJA'
        },
        {
          name: 'Loat Start',
          value: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJvcGVuaWQiOiJvX1UtcTVaYXZPejVXcGxlNkxJZm5sRU5QMTNNIiwiaWF0IjoxNjAwNjA4MDcwLCJleHAiOjE2MDMyMDAwNzB9.152dzJMgmw7l5BJnYOiEaN7umovj9exMgN5LdZfAcR8'
        }
      ]
    },
    created() {
      this.initConfig()
    },

    methods: {
      // 开始刷分
      start() {
        if (this.config.fraction == 'max') {
          this.score.target = 150
        } else {
          var min = 10
          if (this.config && this.config.fraction_min) {
            min = this.config.fraction_min >= 150 ? 150 : this.config.fraction_min
          }
          this.config.fraction_min > 150
          if (this.config) this.score.target = this.random(min, 150)
        }

        this.getArticelIds(0, res => {
          this.status = res.stat
          this.status_msg = res.message
          app.changeTable(1)
          if (res.stat !== 1) return false
          // 打开记录面板
          // 临时修改配置的，暂停重新开始
          // 主要为了清除定时器
          this.stop()
          this.status = 1
          this.timing()
        })
      },
      // 暂停
      stop() {
        if (this.status >= 0) {
          clearInterval(this.timer.interval)
          clearTimeout(this.timer.timeOut)
          this.status = 0
          this.status_msg = '暂停'
        }
      },
      // 输出日志
      addLog(log) {
        if (log) {
          this.log.unshift(log)
        }
      },
      // 获取总分
      getSum() {
        utils.request('https://api.muyiy.cn/yitimini/v1/point/get/sum2').then(res => {
          this.score.today = res.data.todaySum
          this.score.sum = res.data.sum
          let progress = parseInt((res.data.todaySum / this.score.target) * 100)
          utils.progress('progress', progress + '%')

          // 预留一分请求
          if (res.data.todaySum < this.score.target) {
            this.getArticelDetail()
          } else {
            this.status = 0
            this.status_msg = '今天分数刷满'
          }
        })
      },
      // 读取文章信息，并且15s后打卡
      getArticelDetail() {
        // 随机文章ID
        var index = this.random(0, this.articelIds.length - 1)
        // 当前请求的文章ID
        id = this.articelIds[index]

        // 记录当前阅读的ID
        this.readingId = id

        utils.request(
          'https://api.muyiy.cn/yitimini/v1/exercise/add/record',
          `{"version":"1.0.0","labelid":"${this.idsMapLabelid[id]}","issueNumber":"${id}","action":"/v1/exercise/add/record"}`
        ).then(res => {
          this.status = 2
          // 阅读15S
          this.timer.nextTime = 15
          this.timing()
        }).catch(res => {
          this.status = -1
          this.status_msg = '获取文章失败'
        })
      },
      // record 添加分数
      record(id) {
        if (!id) {
          return false
        }

        utils
          .request(
            'https://api.muyiy.cn/yitimini/v1/point/add/record',
            '{"version":"1.0.0","action":"/v1/point/add/record","type":4,"extraId":"' + id + '"}'
          )
          .then(res => {
            this.timer.lastTime = new Date()
            var nextTime = this.random(this.config.time_min, this.config.time_max)
            this.addLog({
              currTime: this.timer.lastTime,
              waitTime: `${nextTime + 15}秒`,
              articelId: id,
              fraction: this.score.today + 1,
              key: this.timer.lastTime.getTime()
            })

            this.score.today += 1
            this.score.sum += 1
            this.status = 1
            this.timer.nextTime = nextTime
            document.title = this.score.today + '/' + this.score.target
            this.timing()
          })
          .catch(res => {
            this.stat = 0
            this.message = res.message
          })
      },
      // 获取随机数
      random(minNum, maxNum) {
        minNum = parseInt(minNum)
        maxNum = parseInt(maxNum)
        switch (arguments.length) {
          case 1:
            return parseInt(Math.random() * minNum + 1, 10)
            break
          case 2:
            return parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10)
            break
          default:
            return 0
            break
        }
      },
      // 计时。到时间自动下一篇文章
      timing() {
        clearTimeout(this.timer.timeOut)
        this.timer.timeOut = setTimeout(() => {
          switch (this.status) {
            case 1:
              // 等待倒计时结束
              this.getSum()
              break
            case 2:
              // 等待阅读结束
              this.record(this.readingId)
              break
          }
        }, this.timer.nextTime * 1000)
        if (this.timer.nextTime > 0) {
          clearTimeout(this.timer.interval)
          this.timer.interval = setInterval(() => {
            this.timer.nextTime -= 1
            if (this.timer.nextTime <= 0) {
              clearInterval(this.timer.interval)
            }
          }, 1000)
        }
      },
      // 切换tab
      changeTable(tabIndex) {
        this.currTab = tabIndex
      },
      // 获取文章ID
      getArticelIds(currIndex = 0, cb) {
        if (currIndex >= utils.typeList.length || this.articelIds.length > 0) {
          cb && cb({ stat: 1, message: '', data: {} })
          return false
        }

        utils
          .request(
            'https://api.muyiy.cn/yitimini/v1/question/questions',
            '{"version":"1.0.0","labelid":"' +
            utils.typeList[currIndex] +
            '","action":"/v1/question/questions"}'
          )
          .then(res => {
            res.data.forEach(item => {
              // 统计文章ID
              this.articelIds.push(item.issueNumber)
              // 文章ID和分类映射
              this.idsMapLabelid[item.issueNumber] = utils.typeList[currIndex]
            })
            this.getArticelIds(currIndex + 1, cb)
          })
          .catch(res => {
            cb && cb(res)
          })
      },
      // 初始化配置
      initConfig() {
        var config = window.localStorage.getItem('config') || '{}'
        this.baseConfig = Object.assign(
          {
            token:
              'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJvcGVuaWQiOiJvX1UtcTVTeGJpaDBzOWdHU1F3YmcwRUc4SUFnIiwiaWF0IjoxNTk5MzE1NDI4LCJleHAiOjE2MDE5MDc0Mjh9.YKqrefWI7FdiqLeNibuknLbWBODpEU8-zPKfmWzkk20',
            time_min: 15,
            time_max: 120,
            fraction: 'max',
            fraction_min: 10
          },
          JSON.parse(config)
        )
      }
    }
  })
</script>

</html>